package service

import (
	"errors"
	"time"

	"gitee.com/war2001/NiuMaEasyGo/model"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

// UserService 用户服务实现
type UserService struct {
	db *gorm.DB
}

// DB 获取数据库连接
func (s *UserService) DB() *gorm.DB {
	return s.db
}

// NewUserService 创建用户服务
func NewUserService(db *gorm.DB) model.UserService {
	return &UserService{
		db: db,
	}
}

// Create 创建用户
func (s *UserService) Create(user *model.User) error {
	// 检查用户名是否已存在
	var count int64
	if err := s.db.Model(&model.User{}).Where("username = ?", user.Username).Count(&count).Error; err != nil {
		return err
	}
	if count > 0 {
		return errors.New("用户名已存在")
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	user.Password = string(hashedPassword)

	// 创建用户
	return s.db.Create(user).Error
}

// GetByID 根据ID获取用户
func (s *UserService) GetByID(id uint) (*model.User, error) {
	var user model.User
	if err := s.db.First(&user, id).Error; err != nil {
		return nil, err
	}
	return &user, nil
}

// GetByUsername 根据用户名获取用户
func (s *UserService) GetByUsername(username string) (*model.User, error) {
	var user model.User
	if err := s.db.Where("username = ?", username).First(&user).Error; err != nil {
		return nil, err
	}
	return &user, nil
}

// Update 更新用户
func (s *UserService) Update(user *model.User) error {
	return s.db.Save(user).Error
}

// Delete 删除用户
func (s *UserService) Delete(id uint) error {
	return s.db.Delete(&model.User{}, id).Error
}

// List 获取用户列表
func (s *UserService) List(page, pageSize int, query map[string]interface{}) ([]*model.User, int64, error) {
	var users []*model.User
	var total int64

	db := s.db.Model(&model.User{})

	// 应用查询条件
	if username, ok := query["username"].(string); ok && username != "" {
		db = db.Where("username LIKE ?", "%"+username+"%")
	}
	if nickname, ok := query["nickname"].(string); ok && nickname != "" {
		db = db.Where("nickname LIKE ?", "%"+nickname+"%")
	}
	if email, ok := query["email"].(string); ok && email != "" {
		db = db.Where("email LIKE ?", "%"+email+"%")
	}
	if phone, ok := query["phone"].(string); ok && phone != "" {
		db = db.Where("phone LIKE ?", "%"+phone+"%")
	}
	if status, ok := query["status"].(int); ok {
		db = db.Where("status = ?", status)
	}

	// 计算总数
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	offset := (page - 1) * pageSize
	if err := db.Offset(offset).Limit(pageSize).Find(&users).Error; err != nil {
		return nil, 0, err
	}

	return users, total, nil
}

// VerifyPassword 验证用户密码
func (s *UserService) VerifyPassword(username, password string) (*model.User, error) {
	// 获取用户
	user, err := s.GetByUsername(username)
	if err != nil {
		return nil, errors.New("用户不存在")
	}

	// 检查用户状态
	if user.Status != 1 {
		return nil, errors.New("用户已被禁用")
	}

	// 验证密码
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		return nil, errors.New("密码错误")
	}

	// 更新最后登录时间和IP
	user.LastLoginAt = time.Now()
	s.db.Model(user).Updates(map[string]interface{}{
		"last_login_at": user.LastLoginAt,
	})

	return user, nil
}

// UpdatePassword 更新用户密码
func (s *UserService) UpdatePassword(id uint, oldPassword, newPassword string) error {
	// 获取用户
	user, err := s.GetByID(id)
	if err != nil {
		return errors.New("用户不存在")
	}

	// 验证旧密码
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(oldPassword))
	if err != nil {
		return errors.New("旧密码错误")
	}

	// 加密新密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	// 更新密码
	user.Password = string(hashedPassword)
	return s.db.Model(user).Update("password", user.Password).Error
}

// ResetPassword 重置用户密码
func (s *UserService) ResetPassword(id uint, newPassword string) error {
	// 获取用户
	user, err := s.GetByID(id)
	if err != nil {
		return errors.New("用户不存在")
	}

	// 加密新密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
	if err != nil {
		return err
	}

	// 更新密码
	user.Password = string(hashedPassword)
	return s.db.Model(user).Update("password", user.Password).Error
}
